package com.bite.friend.service.user.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.common.core.constants.Constants;
import com.bite.common.core.domain.TableDataInfo;
import com.bite.common.core.enums.ExamListType;
import com.bite.common.core.enums.ResultCode;
import com.bite.common.core.utils.ThreadLocalUtil;
import com.bite.common.security.exception.ServiceException;
import com.bite.common.security.service.TokenService;
import com.bite.friend.domain.exam.Exam;
import com.bite.friend.domain.exam.dto.ExamQueryDTO;
import com.bite.friend.domain.exam.vo.ExamVO;
import com.bite.friend.domain.user.UserExam;
import com.bite.friend.domain.user.vo.UserVO;
import com.bite.friend.manager.ExamCacheManager;
import com.bite.friend.manager.UserCacheManager;
import com.bite.friend.mapper.exam.ExamMapper;
import com.bite.friend.mapper.user.UserExamMapper;
import com.bite.friend.service.user.IUserExamService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserExamServiceImpl implements IUserExamService {
    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private UserExamMapper userExamMapper;
    @Autowired
    private TokenService tokenService;
    @Value("${jwt.secret}")
    private  String secret;
    @Autowired
    private ExamCacheManager examCacheManager;

    private UserCacheManager userCacheManager;
    @Override
    public int enter(String token, Long  examId) {
//        //获取当前用户信息 status
//        Long userId=ThreadLocalUtil.get(Constants.USER_ID,Long.class);
//        UserVO user=userCacheManager.getUserById(userId);
//        if(user.getStatus()==0){
//            throw new ServiceException(ResultCode.FAILED_USER_BANNED);
//        }
//
        Exam exam=examMapper.selectById(examId);
        if(exam==null){
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        //已经开赛的不能报名
        if(exam.getStartTime().isBefore(LocalDateTime.now())){
            throw  new ServiceException(ResultCode.EXAM_STARTED);
        }
        //因为我们很多地方都要去获取这个userId,甚至那个身份认证那里也要看一下，这样就有点冗余了
    //    Long userId= tokenService.getUserId(token,secret);
        Long userId= ThreadLocalUtil.get(Constants.USER_ID,Long.class);
        //不能重复报名，从数据库里面判断是否可以报名
        UserExam userExam= userExamMapper.selectOne(new LambdaQueryWrapper<UserExam>()
                .eq(UserExam::getExamId,examId)
                .eq(UserExam::getUserExamId,userId));
        if(userExam!=null){
            throw  new ServiceException(ResultCode.USER_EXAM_HAS_ENTER);
        }
        //此时就说明，我们前提条件满足，可以去报名了
       examCacheManager.addUserExamCache(userId,examId);
        userExam=new UserExam();
        userExam.setExamId(examId);
        userExam.setUserId(userId);
        return userExamMapper.insert(userExam);
    }

    @Override
    public TableDataInfo list(ExamQueryDTO examQueryDto) {
        //从缓存中拿到我的竞赛列表大小
        Long userId=ThreadLocalUtil.get(Constants.USER_ID,Long.class);
        examQueryDto.setType(ExamListType.USER_EXAM_LIST.getValue());
        Long total=examCacheManager.getListSize(examQueryDto.getType(),userId);
        List<ExamVO>examVOList;
        //先查询缓存，并且缓存的key (u:e:l:用户ID),先从缓存中查询，阿吉如查询到，如果查询不到，
        // 从数据库中再去查询，并且将数据库中到数据同步给redis
        if(total==null||total<=0){
            //从数据库中查询我的竞赛列表
            PageHelper.startPage(examQueryDto.getPageNum(),examQueryDto.getPageSize());
            examVOList=userExamMapper.selectUserExamList(userId);
            examCacheManager.refreshCache(examQueryDto.getType(), userId);
            total=new PageInfo<>(examVOList).getTotal();
        }else {
          examVOList=examCacheManager.getExamVOList(examQueryDto,userId);
          total=examCacheManager.getListSize(examQueryDto.getType(),userId);
        }
        if(CollectionUtil.isEmpty(examVOList)){
            return TableDataInfo.empty();
        }

        return TableDataInfo.success(examVOList,total);
    }
}
